package com.oops.service;

import com.oops.constants.Constants;
import com.oops.mapper.TOrderMapper;
import com.oops.model.TOrder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.rocketmq.client.producer.MessageQueueSelector;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * TODO: 订单
 * 
 * @author wuyijie
 * @date 2022/4/16 23:38
 */
@Slf4j
@Service
public class OrderService {
    private final TOrderMapper tOrderMapper;
    private final RocketMQTemplate rocketMqTemplate;
    private final StringRedisTemplate redisTemplate;

    public OrderService(TOrderMapper tOrderMapper, RocketMQTemplate rocketMqTemplate, StringRedisTemplate redisTemplate) {
        this.tOrderMapper = tOrderMapper;
        this.rocketMqTemplate = rocketMqTemplate;
        this.redisTemplate = redisTemplate;
    }

    public void sendMessage(String id) {
        // 顺序消费的话，有两种模式：全局顺序、局部顺序。
        // 全局顺序的话，只能将topic设置一个MessageQueue，但是性能较差
        // 局部顺序的话，因为生产者通过轮训的方式将消息发送到topic的所有MessageQueue，如果要保证消息的顺序发送，可以通过设置MessageQueueSelector来指定消息发送到MessageQueue
        // 比如通过订单id取模，然后选择指定的MessageQueue，保证相同的订单id发送到同一个MessageQueue
        rocketMqTemplate.setMessageQueueSelector(new MessageQueueSelector() {
            @Override
            public MessageQueue select(List<MessageQueue> list, Message message, Object o) {
                return null;
            }
        });
        rocketMqTemplate.asyncSend("test", id, new SendCallback() {
          @Override
          public void onSuccess(SendResult sendResult) {
              log.info("消息成功发送：{}",sendResult);
          }

          @Override
          public void onException(Throwable throwable) {
            log.info("消息发送失败：",throwable);
          }
      });
    }

    /**
     * TODO: 秒杀
     *
     * @author wuyijie
     * @date 2022/4/16 21:44
     * @param goodsId 商品ID
     * @return java.lang.Boolean
     */
    public Boolean seckill(Long goodsId) {
        String key = Constants.SECKILL_GOODS_PREFIX+goodsId;

        Object value = redisTemplate.opsForValue().get(key);
        if (Objects.isNull(value)) {
            log.error("查无此商品id。。。");
            return Boolean.FALSE;
        }

        // 库存
        int stock = Integer.parseInt(value.toString());
        if (stock<1) {
            log.info("该商品已抢完。。。");
            return Boolean.FALSE;
        }

        // 获取锁
        final Boolean lock = redisTemplate.opsForValue().setIfAbsent(Constants.SECKILL_GOODS_LOCK + goodsId, "lock");
        if (Boolean.TRUE.equals(lock)){
            log.info("获取redis锁成功！");
            try {
                // 扣减商品缓存库存
                Long newStock = redisTemplate.opsForValue().decrement(key, 1L);
                log.info("newStock:{}",newStock);
                // 异步发送订单消息到rocketmq
                rocketMqTemplate.asyncSend("order_biz", MessageBuilder.withPayload(goodsId).build(), new SendCallback() {
                    @Override
                    public void onSuccess(SendResult sendResult) {
                        log.info("消息成功发送：{}",sendResult);
                    }
                    @Override
                    public void onException(Throwable throwable) {
                        log.info("消息发送失败：",throwable);
                    }
                }, 3000);
                return Boolean.TRUE;
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                redisTemplate.delete(Constants.SECKILL_GOODS_LOCK + goodsId);
                log.info("删除redis锁成功！");
            }
        }else{
            log.info("加油，暂时未抢到。。。");
            return Boolean.FALSE;
        }
        return Boolean.FALSE;
    }

    /**
     * TODO: 添加订单
     *
     * @author wuyijie
     * @date 2022/4/16 19:27
     * @return com.oops.model.TOrder
     */
    public TOrder add(){
        // 添加订单信息
        TOrder tOrder = new TOrder();
        tOrder.setOrderName("秒杀订单-");
        tOrder.setOrderAmount(BigDecimal.TEN);
        // 未支付
        tOrder.setState(0);
        tOrder.setCreateTime(new Date());
        tOrderMapper.insert(tOrder);

        return tOrder;
    }




    /**
     * TODO: 支付
     *
     * @author wuyijie
     * @date 2022/4/16 19:25
     * @param orderId 订单ID
     * @return java.lang.String
     */
    public String pay(Long orderId) {
        TOrder tOrder = tOrderMapper.selectById(orderId);
        Integer state = tOrder.getState();
        if (Objects.equals(1,state)) {
            return "订单已过期";
        }
        tOrder.setState(2);
        int i = tOrderMapper.updateById(tOrder);
        return "支付成功";
    }
}
